{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Workflow Example: Copper-BOX Catalyst Library Construction\n",
    "\n",
    "This notebook will show a full example of how you might use `molli` to generate a combinatorial catalyst library and extract features."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Necessary imports\n",
    "import molli as ml\n",
    "ml.visual.configure(bgcolor='white')\n",
    "import msgpack\n",
    "import attrs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Part 1: Parsing and Combinatorial Expansion"
   ]
  },
  {
   "attachments": {
    "1_1_BOX.PNG": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here's how to do combinatorial expansion programmatically in Python. We will use an example BOX ligand from a CDXML file\n",
    "\n",
    "![1_1_BOX.PNG](attachment:1_1_BOX.PNG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/3dmoljs_load.v0": "<div id=\"3dmolviewer_17295508778843982\"  style=\"position: relative; width: 100%; height: 500px;\">\n        <p id=\"3dmolwarning_17295508778843982\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n        </div>\n<script>\n\nvar loadScriptAsync = function(uri){\n  return new Promise((resolve, reject) => {\n    //this is to ignore the existence of requirejs amd\n    var savedexports, savedmodule;\n    if (typeof exports !== 'undefined') savedexports = exports;\n    else exports = {}\n    if (typeof module !== 'undefined') savedmodule = module;\n    else module = {}\n\n    var tag = document.createElement('script');\n    tag.src = uri;\n    tag.async = true;\n    tag.onload = () => {\n        exports = savedexports;\n        module = savedmodule;\n        resolve();\n    };\n  var firstScriptTag = document.getElementsByTagName('script')[0];\n  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n});\n};\n\nif(typeof $3Dmolpromise === 'undefined') {\n$3Dmolpromise = null;\n  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n}\n\nvar viewer_17295508778843982 = null;\nvar warn = document.getElementById(\"3dmolwarning_17295508778843982\");\nif(warn) {\n    warn.parentNode.removeChild(warn);\n}\n$3Dmolpromise.then(function() {\nviewer_17295508778843982 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508778843982\"),{backgroundColor:\"white\"});\nviewer_17295508778843982.zoomTo();\n\tviewer_17295508778843982.addModel(\"@<TRIPOS>MOLECULE\\n1_1\\n34 38 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None 1.4551 0.9973 0.0000 N\\n2 None 2.9134 0.6487 0.0000 C\\n3 None 3.6954 1.9292 0.0000 C\\n4 None 2.7204 3.0681 0.0000 O\\n5 None 1.3357 2.4931 0.0000 C\\n6 None 0.0551 3.2737 0.0000 C\\n7 None -1.2629 2.5556 0.0000 C\\n8 None -2.6171 3.2014 0.0000 O\\n9 None -3.6477 2.1112 0.0000 C\\n10 None -2.9296 0.7931 0.0000 C\\n11 None -1.4560 1.0681 0.0000 N\\n12 None -3.2518 0.1160 -1.2988 C\\n13 None 3.2016 -0.0437 1.2989 C\\n14 None 2.1464 -0.8892 1.9485 C\\n15 None 2.4333 -1.5818 3.2470 C\\n16 None 3.7765 -1.4295 3.8975 C\\n17 None 4.8330 -0.5838 3.2484 C\\n18 None 4.5448 0.1086 1.9495 C\\n19 None -4.5864 0.3355 -1.9488 C\\n20 None -4.9071 -0.3427 -3.2482 C\\n21 None -3.8960 -1.2390 -3.8974 C\\n22 None -2.5615 -1.4584 -3.2473 C\\n23 None -2.2395 -0.7805 -1.9475 C\\n24 None -3.6477 2.1112 -1.4789 H\\n25 None 3.6954 1.9292 1.4576 H\\n26 None 0.1884 -0.2611 0.0000 Cu\\n27 None 0.1884 -0.2611 1.8667 Cl\\n28 None -0.6211 -0.7303 -1.8097 Cl\\n29 A1 -4.2170 -1.9163 -5.1957 Unknown\\n30 A1 4.0647 -2.1218 5.1964 Unknown\\n31 None -4.7296 1.0306 0.0000 H\\n32 None 4.7482 0.8764 0.0000 H\\n33 A2 0.7736 3.8645 1.1777 Unknown\\n34 A2 0.0551 3.2737 -1.5603 Unknown\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 6 34 1\\n14 10 12 1\\n15 2 13 1\\n16 13 14 2\\n17 14 15 1\\n18 15 16 2\\n19 16 17 1\\n20 17 18 2\\n21 18 13 1\\n22 12 19 2\\n23 19 20 1\\n24 20 21 2\\n25 21 22 1\\n26 22 23 2\\n27 23 12 1\\n28 21 29 1\\n29 16 30 1\\n30 9 24 1\\n31 3 25 1\\n32 11 26 1\\n33 26 1 1\\n34 26 27 1\\n35 26 28 1\\n36 9 31 1\\n37 3 32 1\\n38 6 33 1\\n\\n\",\"mol2\");\n\tviewer_17295508778843982.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n\tviewer_17295508778843982.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n\tviewer_17295508778843982.zoomTo();\n\tviewer_17295508778843982.setBackgroundColor(\"white\");\nviewer_17295508778843982.render();\n});\n</script>",
      "text/html": [
       "<div id=\"3dmolviewer_17295508778843982\"  style=\"position: relative; width: 100%; height: 500px;\">\n",
       "        <p id=\"3dmolwarning_17295508778843982\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n",
       "        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n",
       "        </div>\n",
       "<script>\n",
       "\n",
       "var loadScriptAsync = function(uri){\n",
       "  return new Promise((resolve, reject) => {\n",
       "    //this is to ignore the existence of requirejs amd\n",
       "    var savedexports, savedmodule;\n",
       "    if (typeof exports !== 'undefined') savedexports = exports;\n",
       "    else exports = {}\n",
       "    if (typeof module !== 'undefined') savedmodule = module;\n",
       "    else module = {}\n",
       "\n",
       "    var tag = document.createElement('script');\n",
       "    tag.src = uri;\n",
       "    tag.async = true;\n",
       "    tag.onload = () => {\n",
       "        exports = savedexports;\n",
       "        module = savedmodule;\n",
       "        resolve();\n",
       "    };\n",
       "  var firstScriptTag = document.getElementsByTagName('script')[0];\n",
       "  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n",
       "});\n",
       "};\n",
       "\n",
       "if(typeof $3Dmolpromise === 'undefined') {\n",
       "$3Dmolpromise = null;\n",
       "  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n",
       "}\n",
       "\n",
       "var viewer_17295508778843982 = null;\n",
       "var warn = document.getElementById(\"3dmolwarning_17295508778843982\");\n",
       "if(warn) {\n",
       "    warn.parentNode.removeChild(warn);\n",
       "}\n",
       "$3Dmolpromise.then(function() {\n",
       "viewer_17295508778843982 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508778843982\"),{backgroundColor:\"white\"});\n",
       "viewer_17295508778843982.zoomTo();\n",
       "\tviewer_17295508778843982.addModel(\"@<TRIPOS>MOLECULE\\n1_1\\n34 38 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None 1.4551 0.9973 0.0000 N\\n2 None 2.9134 0.6487 0.0000 C\\n3 None 3.6954 1.9292 0.0000 C\\n4 None 2.7204 3.0681 0.0000 O\\n5 None 1.3357 2.4931 0.0000 C\\n6 None 0.0551 3.2737 0.0000 C\\n7 None -1.2629 2.5556 0.0000 C\\n8 None -2.6171 3.2014 0.0000 O\\n9 None -3.6477 2.1112 0.0000 C\\n10 None -2.9296 0.7931 0.0000 C\\n11 None -1.4560 1.0681 0.0000 N\\n12 None -3.2518 0.1160 -1.2988 C\\n13 None 3.2016 -0.0437 1.2989 C\\n14 None 2.1464 -0.8892 1.9485 C\\n15 None 2.4333 -1.5818 3.2470 C\\n16 None 3.7765 -1.4295 3.8975 C\\n17 None 4.8330 -0.5838 3.2484 C\\n18 None 4.5448 0.1086 1.9495 C\\n19 None -4.5864 0.3355 -1.9488 C\\n20 None -4.9071 -0.3427 -3.2482 C\\n21 None -3.8960 -1.2390 -3.8974 C\\n22 None -2.5615 -1.4584 -3.2473 C\\n23 None -2.2395 -0.7805 -1.9475 C\\n24 None -3.6477 2.1112 -1.4789 H\\n25 None 3.6954 1.9292 1.4576 H\\n26 None 0.1884 -0.2611 0.0000 Cu\\n27 None 0.1884 -0.2611 1.8667 Cl\\n28 None -0.6211 -0.7303 -1.8097 Cl\\n29 A1 -4.2170 -1.9163 -5.1957 Unknown\\n30 A1 4.0647 -2.1218 5.1964 Unknown\\n31 None -4.7296 1.0306 0.0000 H\\n32 None 4.7482 0.8764 0.0000 H\\n33 A2 0.7736 3.8645 1.1777 Unknown\\n34 A2 0.0551 3.2737 -1.5603 Unknown\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 6 34 1\\n14 10 12 1\\n15 2 13 1\\n16 13 14 2\\n17 14 15 1\\n18 15 16 2\\n19 16 17 1\\n20 17 18 2\\n21 18 13 1\\n22 12 19 2\\n23 19 20 1\\n24 20 21 2\\n25 21 22 1\\n26 22 23 2\\n27 23 12 1\\n28 21 29 1\\n29 16 30 1\\n30 9 24 1\\n31 3 25 1\\n32 11 26 1\\n33 26 1 1\\n34 26 27 1\\n35 26 28 1\\n36 9 31 1\\n37 3 32 1\\n38 6 33 1\\n\\n\",\"mol2\");\n",
       "\tviewer_17295508778843982.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n",
       "\tviewer_17295508778843982.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n",
       "\tviewer_17295508778843982.zoomTo();\n",
       "\tviewer_17295508778843982.setBackgroundColor(\"white\");\n",
       "viewer_17295508778843982.render();\n",
       "});\n",
       "</script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<script>\n            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n                \n                viewer_17295508778843982.render();\n            });\n            </script>",
      "text/html": [
       "<script>\n",
       "            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n",
       "                \n",
       "                viewer_17295508778843982.render();\n",
       "            });\n",
       "            </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Molecule(name='1_1', formula='C19 H4 Cl2 Cu1 N2 O2 Unknown4')"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# first we read in our cores\n",
    "cores = ml.CDXMLFile(ml.files.BOX_cores)\n",
    "\n",
    "example_core = cores['1_1']\n",
    "example_core"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Atom(element=Unknown, isotope=None, label='A1', formal_charge=0, formal_spin=0),\n",
       " Atom(element=Unknown, isotope=None, label='A1', formal_charge=0, formal_spin=0),\n",
       " Atom(element=Unknown, isotope=None, label='A2', formal_charge=0, formal_spin=0),\n",
       " Atom(element=Unknown, isotope=None, label='A2', formal_charge=0, formal_spin=0)]"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Each core has 4 attachment points, 2 labelled A1 (the pendant 4,4' positions), and 2 labelled A2 (the bridging position).\n",
    "attachment_points = [a for a in cores['1_1'].atoms if a.atype == ml.AtomType.AttachmentPoint]\n",
    "attachment_points"
   ]
  },
  {
   "attachments": {
    "BOX_Bridge.PNG": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we will parse out the Bridging groups from the CDXML File, and join them at the bridge-head of the BOX ligand example core!\n",
    "\n",
    "![BOX_Bridge.PNG](attachment:BOX_Bridge.PNG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "There are now 3 molecules created from the first example core.\n"
     ]
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<div id=\"3dmolviewer_17295508779332695\"  style=\"position: relative; width: 100%; height: 500px;\">\n        <p id=\"3dmolwarning_17295508779332695\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n        </div>\n<script>\n\nvar loadScriptAsync = function(uri){\n  return new Promise((resolve, reject) => {\n    //this is to ignore the existence of requirejs amd\n    var savedexports, savedmodule;\n    if (typeof exports !== 'undefined') savedexports = exports;\n    else exports = {}\n    if (typeof module !== 'undefined') savedmodule = module;\n    else module = {}\n\n    var tag = document.createElement('script');\n    tag.src = uri;\n    tag.async = true;\n    tag.onload = () => {\n        exports = savedexports;\n        module = savedmodule;\n        resolve();\n    };\n  var firstScriptTag = document.getElementsByTagName('script')[0];\n  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n});\n};\n\nif(typeof $3Dmolpromise === 'undefined') {\n$3Dmolpromise = null;\n  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n}\n\nvar viewer_17295508779332695 = null;\nvar warn = document.getElementById(\"3dmolwarning_17295508779332695\");\nif(warn) {\n    warn.parentNode.removeChild(warn);\n}\n$3Dmolpromise.then(function() {\nviewer_17295508779332695 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508779332695\"),{backgroundColor:\"white\"});\nviewer_17295508779332695.zoomTo();\n\tviewer_17295508779332695.addModel(\"@<TRIPOS>MOLECULE\\n1_1_Me\\n34 38 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None 1.4000 -2.2764 0.0000 N\\n2 None 2.8583 -2.6250 0.0000 C\\n3 None 3.6403 -1.3444 0.0000 C\\n4 None 2.6653 -0.2056 0.0000 O\\n5 None 1.2806 -0.7806 0.0000 C\\n6 None 0.0000 0.0000 0.0000 C\\n7 None -1.3181 -0.7181 0.0000 C\\n8 None -2.6722 -0.0722 0.0000 O\\n9 None -3.7028 -1.1625 0.0000 C\\n10 None -2.9847 -2.4806 0.0000 C\\n11 None -1.5111 -2.2056 0.0000 N\\n12 None -3.3069 -3.1576 -1.2988 C\\n13 None 3.1465 -3.3174 1.2989 C\\n14 None 2.0913 -4.1628 1.9485 C\\n15 None 2.3782 -4.8554 3.2470 C\\n16 None 3.7214 -4.7031 3.8975 C\\n17 None 4.7779 -3.8574 3.2484 C\\n18 None 4.4897 -3.1651 1.9495 C\\n19 None -4.6415 -2.9382 -1.9488 C\\n20 None -4.9622 -3.6164 -3.2482 C\\n21 None -3.9511 -4.5126 -3.8974 C\\n22 None -2.6166 -4.7321 -3.2473 C\\n23 None -2.2946 -4.0542 -1.9475 C\\n24 None -3.7028 -1.1625 -1.4789 H\\n25 None 3.6403 -1.3444 1.4576 H\\n26 None 0.1333 -3.5347 0.0000 Cu\\n27 None 0.1333 -3.5347 1.8667 Cl\\n28 None -0.6762 -4.0040 -1.8097 Cl\\n29 A1 -4.2721 -5.1900 -5.1957 Unknown\\n30 A1 4.0096 -5.3955 5.1964 Unknown\\n31 None -4.7847 -2.2431 0.0000 H\\n32 None 4.6931 -2.3972 0.0000 H\\n33 None 0.7182 0.5906 1.1771 C\\n34 None 0.0000 0.0000 -1.5000 C\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 21 29 1\\n28 16 30 1\\n29 9 24 1\\n30 3 25 1\\n31 11 26 1\\n32 26 1 1\\n33 26 27 1\\n34 26 28 1\\n35 9 31 1\\n36 3 32 1\\n37 6 33 1\\n38 6 34 1\\n\\n\",\"mol2\");\n\tviewer_17295508779332695.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n\tviewer_17295508779332695.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n\tviewer_17295508779332695.zoomTo();\n\tviewer_17295508779332695.setBackgroundColor(\"white\");\nviewer_17295508779332695.render();\n});\n</script>",
      "text/html": [
       "<div id=\"3dmolviewer_17295508779332695\"  style=\"position: relative; width: 100%; height: 500px;\">\n",
       "        <p id=\"3dmolwarning_17295508779332695\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n",
       "        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n",
       "        </div>\n",
       "<script>\n",
       "\n",
       "var loadScriptAsync = function(uri){\n",
       "  return new Promise((resolve, reject) => {\n",
       "    //this is to ignore the existence of requirejs amd\n",
       "    var savedexports, savedmodule;\n",
       "    if (typeof exports !== 'undefined') savedexports = exports;\n",
       "    else exports = {}\n",
       "    if (typeof module !== 'undefined') savedmodule = module;\n",
       "    else module = {}\n",
       "\n",
       "    var tag = document.createElement('script');\n",
       "    tag.src = uri;\n",
       "    tag.async = true;\n",
       "    tag.onload = () => {\n",
       "        exports = savedexports;\n",
       "        module = savedmodule;\n",
       "        resolve();\n",
       "    };\n",
       "  var firstScriptTag = document.getElementsByTagName('script')[0];\n",
       "  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n",
       "});\n",
       "};\n",
       "\n",
       "if(typeof $3Dmolpromise === 'undefined') {\n",
       "$3Dmolpromise = null;\n",
       "  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n",
       "}\n",
       "\n",
       "var viewer_17295508779332695 = null;\n",
       "var warn = document.getElementById(\"3dmolwarning_17295508779332695\");\n",
       "if(warn) {\n",
       "    warn.parentNode.removeChild(warn);\n",
       "}\n",
       "$3Dmolpromise.then(function() {\n",
       "viewer_17295508779332695 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508779332695\"),{backgroundColor:\"white\"});\n",
       "viewer_17295508779332695.zoomTo();\n",
       "\tviewer_17295508779332695.addModel(\"@<TRIPOS>MOLECULE\\n1_1_Me\\n34 38 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None 1.4000 -2.2764 0.0000 N\\n2 None 2.8583 -2.6250 0.0000 C\\n3 None 3.6403 -1.3444 0.0000 C\\n4 None 2.6653 -0.2056 0.0000 O\\n5 None 1.2806 -0.7806 0.0000 C\\n6 None 0.0000 0.0000 0.0000 C\\n7 None -1.3181 -0.7181 0.0000 C\\n8 None -2.6722 -0.0722 0.0000 O\\n9 None -3.7028 -1.1625 0.0000 C\\n10 None -2.9847 -2.4806 0.0000 C\\n11 None -1.5111 -2.2056 0.0000 N\\n12 None -3.3069 -3.1576 -1.2988 C\\n13 None 3.1465 -3.3174 1.2989 C\\n14 None 2.0913 -4.1628 1.9485 C\\n15 None 2.3782 -4.8554 3.2470 C\\n16 None 3.7214 -4.7031 3.8975 C\\n17 None 4.7779 -3.8574 3.2484 C\\n18 None 4.4897 -3.1651 1.9495 C\\n19 None -4.6415 -2.9382 -1.9488 C\\n20 None -4.9622 -3.6164 -3.2482 C\\n21 None -3.9511 -4.5126 -3.8974 C\\n22 None -2.6166 -4.7321 -3.2473 C\\n23 None -2.2946 -4.0542 -1.9475 C\\n24 None -3.7028 -1.1625 -1.4789 H\\n25 None 3.6403 -1.3444 1.4576 H\\n26 None 0.1333 -3.5347 0.0000 Cu\\n27 None 0.1333 -3.5347 1.8667 Cl\\n28 None -0.6762 -4.0040 -1.8097 Cl\\n29 A1 -4.2721 -5.1900 -5.1957 Unknown\\n30 A1 4.0096 -5.3955 5.1964 Unknown\\n31 None -4.7847 -2.2431 0.0000 H\\n32 None 4.6931 -2.3972 0.0000 H\\n33 None 0.7182 0.5906 1.1771 C\\n34 None 0.0000 0.0000 -1.5000 C\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 21 29 1\\n28 16 30 1\\n29 9 24 1\\n30 3 25 1\\n31 11 26 1\\n32 26 1 1\\n33 26 27 1\\n34 26 28 1\\n35 9 31 1\\n36 3 32 1\\n37 6 33 1\\n38 6 34 1\\n\\n\",\"mol2\");\n",
       "\tviewer_17295508779332695.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n",
       "\tviewer_17295508779332695.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n",
       "\tviewer_17295508779332695.zoomTo();\n",
       "\tviewer_17295508779332695.setBackgroundColor(\"white\");\n",
       "viewer_17295508779332695.render();\n",
       "});\n",
       "</script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<script>\n            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n                \n                viewer_17295508779332695.render();\n            });\n            </script>",
      "text/html": [
       "<script>\n",
       "            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n",
       "                \n",
       "                viewer_17295508779332695.render();\n",
       "            });\n",
       "            </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Molecule(name='1_1_Me', formula='C21 H4 Cl2 Cu1 N2 O2 Unknown2')"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# now we will expand the bridging groups\n",
    "bridging_groups = ml.CDXMLFile(ml.files.BOX_bridge)\n",
    "\n",
    "# this will be our exapnded collection\n",
    "cores_and_bridge_mols = []\n",
    "\n",
    "# make a molecule for each core + bridging groups\n",
    "for bridging_fragment in bridging_groups.keys():\n",
    "    # get our bridge structure - molli assigns default 'AP1' label to attachment points without chemdraw-specified labels\n",
    "    bridge_mol = bridging_groups[bridging_fragment]\n",
    "    # join one bridging group fragment\n",
    "    expanded = ml.Molecule.join(example_core, bridge_mol, 'A2', 'AP1')\n",
    "    #join the other\n",
    "    expanded = ml.Molecule.join(expanded, bridge_mol, 'A2', 'AP1', name = '_'.join([example_core.name, bridge_mol.name]))\n",
    "    # add to our collection\n",
    "    cores_and_bridge_mols.append(expanded)\n",
    "\n",
    "print(f'There are now {len(cores_and_bridge_mols)} molecules created from the first example core.')\n",
    "\n",
    "expanded"
   ]
  },
  {
   "attachments": {
    "BOX_C4.PNG": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we will expand to a subset of the C4 substituents shown below:\n",
    "\n",
    "![BOX_C4.PNG](attachment:BOX_C4.PNG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "There are now 12 molecules created from the first example core.\n"
     ]
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<div id=\"3dmolviewer_17295508780057697\"  style=\"position: relative; width: 100%; height: 500px;\">\n        <p id=\"3dmolwarning_17295508780057697\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n        </div>\n<script>\n\nvar loadScriptAsync = function(uri){\n  return new Promise((resolve, reject) => {\n    //this is to ignore the existence of requirejs amd\n    var savedexports, savedmodule;\n    if (typeof exports !== 'undefined') savedexports = exports;\n    else exports = {}\n    if (typeof module !== 'undefined') savedmodule = module;\n    else module = {}\n\n    var tag = document.createElement('script');\n    tag.src = uri;\n    tag.async = true;\n    tag.onload = () => {\n        exports = savedexports;\n        module = savedmodule;\n        resolve();\n    };\n  var firstScriptTag = document.getElementsByTagName('script')[0];\n  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n});\n};\n\nif(typeof $3Dmolpromise === 'undefined') {\n$3Dmolpromise = null;\n  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n}\n\nvar viewer_17295508780057697 = null;\nvar warn = document.getElementById(\"3dmolwarning_17295508780057697\");\nif(warn) {\n    warn.parentNode.removeChild(warn);\n}\n$3Dmolpromise.then(function() {\nviewer_17295508780057697 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508780057697\"),{backgroundColor:\"white\"});\nviewer_17295508780057697.zoomTo();\n\tviewer_17295508780057697.addModel(\"@<TRIPOS>MOLECULE\\n410_1_1_Me\\n62 68 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None -2.3214 2.4267 -3.8975 N\\n2 None -0.8631 2.0781 -3.8975 C\\n3 None -0.0811 3.3587 -3.8975 C\\n4 None -1.0561 4.4976 -3.8975 O\\n5 None -2.4408 3.9226 -3.8975 C\\n6 None -3.7214 4.7031 -3.8975 C\\n7 None -5.0394 3.9851 -3.8975 C\\n8 None -6.3936 4.6309 -3.8975 O\\n9 None -7.4242 3.5406 -3.8975 C\\n10 None -6.7061 2.2226 -3.8975 C\\n11 None -5.2325 2.4976 -3.8975 N\\n12 None -7.0283 1.5455 -5.1963 C\\n13 None -0.5749 1.3858 -2.5985 C\\n14 None -1.6301 0.5403 -1.9490 C\\n15 None -1.3432 -0.1523 -0.6505 C\\n16 None 0.0000 0.0000 0.0000 C\\n17 None 1.0565 0.8457 -0.6491 C\\n18 None 0.7683 1.5381 -1.9480 C\\n19 None -8.3629 1.7649 -5.8463 C\\n20 None -8.6836 1.0868 -7.1457 C\\n21 None -7.6725 0.1905 -7.7949 C\\n22 None -6.3380 -0.0290 -7.1448 C\\n23 None -6.0160 0.6489 -5.8450 C\\n24 None -7.4242 3.5406 -5.3764 H\\n25 None -0.0811 3.3587 -2.4399 H\\n26 None -3.5881 1.1684 -3.8975 Cu\\n27 None -3.5881 1.1684 -2.0307 Cl\\n28 None -4.3976 0.6992 -5.7072 Cl\\n29 None -8.5061 2.4601 -3.8975 H\\n30 None 0.9717 2.3059 -3.8975 H\\n31 None -3.0032 5.2937 -2.7204 C\\n32 None -3.7214 4.7031 -5.3975 C\\n33 None -5.6354 -4.1991 -10.0483 C\\n34 None -6.6762 -3.7043 -11.0080 C\\n35 None -5.3807 -3.4566 -8.7705 C\\n36 None -6.1668 -2.2193 -8.4524 C\\n37 None -7.2076 -1.7245 -9.4121 C\\n38 None -7.4622 -2.4671 -10.6898 C\\n39 None -7.9937 -0.4873 -9.0939 C\\n40 None -8.5037 -1.9724 -11.6507 C\\n41 None -4.8493 -5.4364 -10.3665 C\\n42 None -3.8085 -5.9311 -9.4068 F\\n43 None -5.8846 -6.2720 -9.6745 F\\n44 None -4.5946 -4.6939 -9.0887 F\\n45 None -8.7584 -2.7149 -12.9284 F\\n46 None -9.2898 -0.7351 -11.3325 F\\n47 None -9.5390 -2.8081 -10.9587 F\\n48 None 3.8337 -3.4633 1.3435 C\\n49 None 3.0140 -3.2741 2.5850 C\\n50 None 3.4715 -2.7288 0.0872 C\\n51 None 2.2897 -1.8052 0.0724 C\\n52 None 1.4700 -1.6160 1.3139 C\\n53 None 1.8322 -2.3505 2.5702 C\\n54 None 0.2882 -0.6924 1.2990 C\\n55 None 1.0123 -2.1616 3.8130 C\\n56 None 5.0155 -4.3869 1.3583 C\\n57 None 5.8351 -4.5761 0.1168 F\\n58 None 5.9004 -3.2480 1.7690 F\\n59 None 4.6533 -3.6524 0.1020 F\\n60 None 1.3745 -2.8961 5.0693 F\\n61 None -0.1695 -1.2380 3.7982 F\\n62 None 1.8972 -1.0227 4.2237 F\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 9 24 1\\n28 3 25 1\\n29 11 26 1\\n30 26 1 1\\n31 26 27 1\\n32 26 28 1\\n33 9 29 1\\n34 3 30 1\\n35 6 31 1\\n36 6 32 1\\n37 33 34 2\\n38 33 35 1\\n39 35 36 2\\n40 36 37 1\\n41 37 38 2\\n42 38 34 1\\n43 37 39 1\\n44 38 40 1\\n45 33 41 1\\n46 41 42 1\\n47 41 43 1\\n48 41 44 1\\n49 40 45 1\\n50 40 46 1\\n51 40 47 1\\n52 21 39 1\\n53 48 49 2\\n54 48 50 1\\n55 50 51 2\\n56 51 52 1\\n57 52 53 2\\n58 53 49 1\\n59 52 54 1\\n60 53 55 1\\n61 48 56 1\\n62 56 57 1\\n63 56 58 1\\n64 56 59 1\\n65 55 60 1\\n66 55 61 1\\n67 55 62 1\\n68 16 54 1\\n\\n\",\"mol2\");\n\tviewer_17295508780057697.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n\tviewer_17295508780057697.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n\tviewer_17295508780057697.zoomTo();\n\tviewer_17295508780057697.setBackgroundColor(\"white\");\nviewer_17295508780057697.render();\n});\n</script>",
      "text/html": [
       "<div id=\"3dmolviewer_17295508780057697\"  style=\"position: relative; width: 100%; height: 500px;\">\n",
       "        <p id=\"3dmolwarning_17295508780057697\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n",
       "        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n",
       "        </div>\n",
       "<script>\n",
       "\n",
       "var loadScriptAsync = function(uri){\n",
       "  return new Promise((resolve, reject) => {\n",
       "    //this is to ignore the existence of requirejs amd\n",
       "    var savedexports, savedmodule;\n",
       "    if (typeof exports !== 'undefined') savedexports = exports;\n",
       "    else exports = {}\n",
       "    if (typeof module !== 'undefined') savedmodule = module;\n",
       "    else module = {}\n",
       "\n",
       "    var tag = document.createElement('script');\n",
       "    tag.src = uri;\n",
       "    tag.async = true;\n",
       "    tag.onload = () => {\n",
       "        exports = savedexports;\n",
       "        module = savedmodule;\n",
       "        resolve();\n",
       "    };\n",
       "  var firstScriptTag = document.getElementsByTagName('script')[0];\n",
       "  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n",
       "});\n",
       "};\n",
       "\n",
       "if(typeof $3Dmolpromise === 'undefined') {\n",
       "$3Dmolpromise = null;\n",
       "  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n",
       "}\n",
       "\n",
       "var viewer_17295508780057697 = null;\n",
       "var warn = document.getElementById(\"3dmolwarning_17295508780057697\");\n",
       "if(warn) {\n",
       "    warn.parentNode.removeChild(warn);\n",
       "}\n",
       "$3Dmolpromise.then(function() {\n",
       "viewer_17295508780057697 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508780057697\"),{backgroundColor:\"white\"});\n",
       "viewer_17295508780057697.zoomTo();\n",
       "\tviewer_17295508780057697.addModel(\"@<TRIPOS>MOLECULE\\n410_1_1_Me\\n62 68 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None -2.3214 2.4267 -3.8975 N\\n2 None -0.8631 2.0781 -3.8975 C\\n3 None -0.0811 3.3587 -3.8975 C\\n4 None -1.0561 4.4976 -3.8975 O\\n5 None -2.4408 3.9226 -3.8975 C\\n6 None -3.7214 4.7031 -3.8975 C\\n7 None -5.0394 3.9851 -3.8975 C\\n8 None -6.3936 4.6309 -3.8975 O\\n9 None -7.4242 3.5406 -3.8975 C\\n10 None -6.7061 2.2226 -3.8975 C\\n11 None -5.2325 2.4976 -3.8975 N\\n12 None -7.0283 1.5455 -5.1963 C\\n13 None -0.5749 1.3858 -2.5985 C\\n14 None -1.6301 0.5403 -1.9490 C\\n15 None -1.3432 -0.1523 -0.6505 C\\n16 None 0.0000 0.0000 0.0000 C\\n17 None 1.0565 0.8457 -0.6491 C\\n18 None 0.7683 1.5381 -1.9480 C\\n19 None -8.3629 1.7649 -5.8463 C\\n20 None -8.6836 1.0868 -7.1457 C\\n21 None -7.6725 0.1905 -7.7949 C\\n22 None -6.3380 -0.0290 -7.1448 C\\n23 None -6.0160 0.6489 -5.8450 C\\n24 None -7.4242 3.5406 -5.3764 H\\n25 None -0.0811 3.3587 -2.4399 H\\n26 None -3.5881 1.1684 -3.8975 Cu\\n27 None -3.5881 1.1684 -2.0307 Cl\\n28 None -4.3976 0.6992 -5.7072 Cl\\n29 None -8.5061 2.4601 -3.8975 H\\n30 None 0.9717 2.3059 -3.8975 H\\n31 None -3.0032 5.2937 -2.7204 C\\n32 None -3.7214 4.7031 -5.3975 C\\n33 None -5.6354 -4.1991 -10.0483 C\\n34 None -6.6762 -3.7043 -11.0080 C\\n35 None -5.3807 -3.4566 -8.7705 C\\n36 None -6.1668 -2.2193 -8.4524 C\\n37 None -7.2076 -1.7245 -9.4121 C\\n38 None -7.4622 -2.4671 -10.6898 C\\n39 None -7.9937 -0.4873 -9.0939 C\\n40 None -8.5037 -1.9724 -11.6507 C\\n41 None -4.8493 -5.4364 -10.3665 C\\n42 None -3.8085 -5.9311 -9.4068 F\\n43 None -5.8846 -6.2720 -9.6745 F\\n44 None -4.5946 -4.6939 -9.0887 F\\n45 None -8.7584 -2.7149 -12.9284 F\\n46 None -9.2898 -0.7351 -11.3325 F\\n47 None -9.5390 -2.8081 -10.9587 F\\n48 None 3.8337 -3.4633 1.3435 C\\n49 None 3.0140 -3.2741 2.5850 C\\n50 None 3.4715 -2.7288 0.0872 C\\n51 None 2.2897 -1.8052 0.0724 C\\n52 None 1.4700 -1.6160 1.3139 C\\n53 None 1.8322 -2.3505 2.5702 C\\n54 None 0.2882 -0.6924 1.2990 C\\n55 None 1.0123 -2.1616 3.8130 C\\n56 None 5.0155 -4.3869 1.3583 C\\n57 None 5.8351 -4.5761 0.1168 F\\n58 None 5.9004 -3.2480 1.7690 F\\n59 None 4.6533 -3.6524 0.1020 F\\n60 None 1.3745 -2.8961 5.0693 F\\n61 None -0.1695 -1.2380 3.7982 F\\n62 None 1.8972 -1.0227 4.2237 F\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 9 24 1\\n28 3 25 1\\n29 11 26 1\\n30 26 1 1\\n31 26 27 1\\n32 26 28 1\\n33 9 29 1\\n34 3 30 1\\n35 6 31 1\\n36 6 32 1\\n37 33 34 2\\n38 33 35 1\\n39 35 36 2\\n40 36 37 1\\n41 37 38 2\\n42 38 34 1\\n43 37 39 1\\n44 38 40 1\\n45 33 41 1\\n46 41 42 1\\n47 41 43 1\\n48 41 44 1\\n49 40 45 1\\n50 40 46 1\\n51 40 47 1\\n52 21 39 1\\n53 48 49 2\\n54 48 50 1\\n55 50 51 2\\n56 51 52 1\\n57 52 53 2\\n58 53 49 1\\n59 52 54 1\\n60 53 55 1\\n61 48 56 1\\n62 56 57 1\\n63 56 58 1\\n64 56 59 1\\n65 55 60 1\\n66 55 61 1\\n67 55 62 1\\n68 16 54 1\\n\\n\",\"mol2\");\n",
       "\tviewer_17295508780057697.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n",
       "\tviewer_17295508780057697.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n",
       "\tviewer_17295508780057697.zoomTo();\n",
       "\tviewer_17295508780057697.setBackgroundColor(\"white\");\n",
       "viewer_17295508780057697.render();\n",
       "});\n",
       "</script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<script>\n            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n                \n                viewer_17295508780057697.render();\n            });\n            </script>",
      "text/html": [
       "<script>\n",
       "            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n",
       "                \n",
       "                viewer_17295508780057697.render();\n",
       "            });\n",
       "            </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Molecule(name='410_1_1_Me', formula='C39 H4 Cl2 Cu1 F12 N2 O2')"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# now we will expand the bridging groups\n",
    "four_positions = ml.CDXMLFile(ml.files.BOX_4_position)\n",
    "\n",
    "c4_keys = [\"407\", \"408\", \"409\", \"410\"]\n",
    "\n",
    "# this will be our exapnded collection\n",
    "fully_expanded_mols = []\n",
    "\n",
    "for core_and_bridge in cores_and_bridge_mols:\n",
    "\n",
    "    # make a molecule for each core + bridging groups\n",
    "    for pos4 in c4_keys:\n",
    "        # get our 4-position fragment\n",
    "        pos4_mol = four_positions[pos4]\n",
    "        # join one 4-position group fragment\n",
    "        expanded = ml.Molecule.join(core_and_bridge, pos4_mol, 'A1', 'AP1')\n",
    "        #join the other\n",
    "        expanded = ml.Molecule.join(expanded, pos4_mol, 'A1', 'AP1', name = '_'.join([ pos4_mol.name, core_and_bridge.name]))\n",
    "        # add to our collection\n",
    "        fully_expanded_mols.append(expanded)\n",
    "\n",
    "print(f'There are now {len(fully_expanded_mols)} molecules created from the first example core.')\n",
    "\n",
    "expanded"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Part 2: Adding Hydrogens and Optimization\n",
    "\n",
    "`CDXML` does not natively parse hydrogens, although `molli` has the ability to read these directly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/3dmoljs_load.v0": "<div id=\"3dmolviewer_17295508781583483\"  style=\"position: relative; width: 100%; height: 500px;\">\n        <p id=\"3dmolwarning_17295508781583483\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n        </div>\n<script>\n\nvar loadScriptAsync = function(uri){\n  return new Promise((resolve, reject) => {\n    //this is to ignore the existence of requirejs amd\n    var savedexports, savedmodule;\n    if (typeof exports !== 'undefined') savedexports = exports;\n    else exports = {}\n    if (typeof module !== 'undefined') savedmodule = module;\n    else module = {}\n\n    var tag = document.createElement('script');\n    tag.src = uri;\n    tag.async = true;\n    tag.onload = () => {\n        exports = savedexports;\n        module = savedmodule;\n        resolve();\n    };\n  var firstScriptTag = document.getElementsByTagName('script')[0];\n  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n});\n};\n\nif(typeof $3Dmolpromise === 'undefined') {\n$3Dmolpromise = null;\n  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n}\n\nvar viewer_17295508781583483 = null;\nvar warn = document.getElementById(\"3dmolwarning_17295508781583483\");\nif(warn) {\n    warn.parentNode.removeChild(warn);\n}\n$3Dmolpromise.then(function() {\nviewer_17295508781583483 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508781583483\"),{backgroundColor:\"white\"});\nviewer_17295508781583483.zoomTo();\n\tviewer_17295508781583483.addModel(\"@<TRIPOS>MOLECULE\\n410_1_1_Me\\n88 94 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None -2.3214 2.4267 -3.8975 N\\n2 None -0.8631 2.0781 -3.8975 C\\n3 None -0.0811 3.3587 -3.8975 C\\n4 None -1.0561 4.4976 -3.8975 O\\n5 None -2.4408 3.9226 -3.8975 C\\n6 None -3.7214 4.7031 -3.8975 C\\n7 None -5.0394 3.9851 -3.8975 C\\n8 None -6.3936 4.6309 -3.8975 O\\n9 None -7.4242 3.5406 -3.8975 C\\n10 None -6.7061 2.2226 -3.8975 C\\n11 None -5.2325 2.4976 -3.8975 N\\n12 None -7.0283 1.5455 -5.1963 C\\n13 None -0.5749 1.3858 -2.5985 C\\n14 None -1.6301 0.5403 -1.9490 C\\n15 None -1.3432 -0.1523 -0.6505 C\\n16 None 0.0000 0.0000 0.0000 C\\n17 None 1.0565 0.8457 -0.6491 C\\n18 None 0.7683 1.5381 -1.9480 C\\n19 None -8.3629 1.7649 -5.8463 C\\n20 None -8.6836 1.0868 -7.1457 C\\n21 None -7.6725 0.1905 -7.7949 C\\n22 None -6.3380 -0.0290 -7.1448 C\\n23 None -6.0160 0.6489 -5.8450 C\\n24 None -7.4242 3.5406 -5.3764 H\\n25 None -0.0811 3.3587 -2.4399 H\\n26 None -3.5881 1.1684 -3.8975 Cu\\n27 None -3.5881 1.1684 -2.0307 Cl\\n28 None -4.3976 0.6992 -5.7072 Cl\\n29 None -8.5061 2.4601 -3.8975 H\\n30 None 0.9717 2.3059 -3.8975 H\\n31 None -3.0032 5.2937 -2.7204 C\\n32 None -3.7214 4.7031 -5.3975 C\\n33 None -5.6354 -4.1991 -10.0483 C\\n34 None -6.6762 -3.7043 -11.0080 C\\n35 None -5.3807 -3.4566 -8.7705 C\\n36 None -6.1668 -2.2193 -8.4524 C\\n37 None -7.2076 -1.7245 -9.4121 C\\n38 None -7.4622 -2.4671 -10.6898 C\\n39 None -7.9937 -0.4873 -9.0939 C\\n40 None -8.5037 -1.9724 -11.6507 C\\n41 None -4.8493 -5.4364 -10.3665 C\\n42 None -3.8085 -5.9311 -9.4068 F\\n43 None -5.8846 -6.2720 -9.6745 F\\n44 None -4.5946 -4.6939 -9.0887 F\\n45 None -8.7584 -2.7149 -12.9284 F\\n46 None -9.2898 -0.7351 -11.3325 F\\n47 None -9.5390 -2.8081 -10.9587 F\\n48 None 3.8337 -3.4633 1.3435 C\\n49 None 3.0140 -3.2741 2.5850 C\\n50 None 3.4715 -2.7288 0.0872 C\\n51 None 2.2897 -1.8052 0.0724 C\\n52 None 1.4700 -1.6160 1.3139 C\\n53 None 1.8322 -2.3505 2.5702 C\\n54 None 0.2882 -0.6924 1.2990 C\\n55 None 1.0123 -2.1616 3.8130 C\\n56 None 5.0155 -4.3869 1.3583 C\\n57 None 5.8351 -4.5761 0.1168 F\\n58 None 5.9004 -3.2480 1.7690 F\\n59 None 4.6533 -3.6524 0.1020 F\\n60 None 1.3745 -2.8961 5.0693 F\\n61 None -0.1695 -1.2380 3.7982 F\\n62 None 1.8972 -1.0227 4.2237 F\\n63 None -0.6071 1.4629 -4.7347 H\\n64 None -6.9925 1.6208 -3.0604 H\\n65 None -2.5884 0.4312 -2.4123 H\\n66 None -2.0967 -0.7551 -0.1882 H\\n67 None 2.0149 0.9550 -0.1859 H\\n68 None 1.5214 2.1410 -2.4109 H\\n69 None -9.0853 2.4045 -5.3837 H\\n70 None -9.6349 1.2426 -7.6101 H\\n71 None -5.6161 -0.6687 -7.6080 H\\n72 None -5.0647 0.4931 -5.3807 H\\n73 None -2.8977 4.5509 -1.9576 H\\n74 None -3.5648 6.1204 -2.3381 H\\n75 None -2.0349 5.6312 -3.0260 H\\n76 None -2.7126 4.7031 -5.7542 H\\n77 None -4.2258 5.5768 -5.7542 H\\n78 None -4.2258 3.8295 -5.7542 H\\n79 None -6.8579 -4.2341 -11.9197 H\\n80 None -4.6381 -3.8096 -8.0858 H\\n81 None -5.9851 -1.6895 -7.5407 H\\n82 None -7.8182 0.2183 -9.8790 H\\n83 None -9.0285 -0.7586 -9.0701 H\\n84 None 3.2724 -3.7982 3.4814 H\\n85 None 4.0563 -2.8638 -0.7986 H\\n86 None 2.0313 -1.2812 -0.8240 H\\n87 None -0.5758 -1.2684 1.5573 H\\n88 None 0.4587 0.0630 2.0375 H\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 9 24 1\\n28 3 25 1\\n29 11 26 1\\n30 26 1 1\\n31 26 27 1\\n32 26 28 1\\n33 9 29 1\\n34 3 30 1\\n35 6 31 1\\n36 6 32 1\\n37 33 34 2\\n38 33 35 1\\n39 35 36 2\\n40 36 37 1\\n41 37 38 2\\n42 38 34 1\\n43 37 39 1\\n44 38 40 1\\n45 33 41 1\\n46 41 42 1\\n47 41 43 1\\n48 41 44 1\\n49 40 45 1\\n50 40 46 1\\n51 40 47 1\\n52 21 39 1\\n53 48 49 2\\n54 48 50 1\\n55 50 51 2\\n56 51 52 1\\n57 52 53 2\\n58 53 49 1\\n59 52 54 1\\n60 53 55 1\\n61 48 56 1\\n62 56 57 1\\n63 56 58 1\\n64 56 59 1\\n65 55 60 1\\n66 55 61 1\\n67 55 62 1\\n68 16 54 1\\n69 2 63 1\\n70 10 64 1\\n71 14 65 1\\n72 15 66 1\\n73 17 67 1\\n74 18 68 1\\n75 19 69 1\\n76 20 70 1\\n77 22 71 1\\n78 23 72 1\\n79 31 73 1\\n80 31 74 1\\n81 31 75 1\\n82 32 76 1\\n83 32 77 1\\n84 32 78 1\\n85 34 79 1\\n86 35 80 1\\n87 36 81 1\\n88 39 82 1\\n89 39 83 1\\n90 49 84 1\\n91 50 85 1\\n92 51 86 1\\n93 54 87 1\\n94 54 88 1\\n\\n\",\"mol2\");\n\tviewer_17295508781583483.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n\tviewer_17295508781583483.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n\tviewer_17295508781583483.zoomTo();\n\tviewer_17295508781583483.setBackgroundColor(\"white\");\nviewer_17295508781583483.render();\n});\n</script>",
      "text/html": [
       "<div id=\"3dmolviewer_17295508781583483\"  style=\"position: relative; width: 100%; height: 500px;\">\n",
       "        <p id=\"3dmolwarning_17295508781583483\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n",
       "        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n",
       "        </div>\n",
       "<script>\n",
       "\n",
       "var loadScriptAsync = function(uri){\n",
       "  return new Promise((resolve, reject) => {\n",
       "    //this is to ignore the existence of requirejs amd\n",
       "    var savedexports, savedmodule;\n",
       "    if (typeof exports !== 'undefined') savedexports = exports;\n",
       "    else exports = {}\n",
       "    if (typeof module !== 'undefined') savedmodule = module;\n",
       "    else module = {}\n",
       "\n",
       "    var tag = document.createElement('script');\n",
       "    tag.src = uri;\n",
       "    tag.async = true;\n",
       "    tag.onload = () => {\n",
       "        exports = savedexports;\n",
       "        module = savedmodule;\n",
       "        resolve();\n",
       "    };\n",
       "  var firstScriptTag = document.getElementsByTagName('script')[0];\n",
       "  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n",
       "});\n",
       "};\n",
       "\n",
       "if(typeof $3Dmolpromise === 'undefined') {\n",
       "$3Dmolpromise = null;\n",
       "  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n",
       "}\n",
       "\n",
       "var viewer_17295508781583483 = null;\n",
       "var warn = document.getElementById(\"3dmolwarning_17295508781583483\");\n",
       "if(warn) {\n",
       "    warn.parentNode.removeChild(warn);\n",
       "}\n",
       "$3Dmolpromise.then(function() {\n",
       "viewer_17295508781583483 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295508781583483\"),{backgroundColor:\"white\"});\n",
       "viewer_17295508781583483.zoomTo();\n",
       "\tviewer_17295508781583483.addModel(\"@<TRIPOS>MOLECULE\\n410_1_1_Me\\n88 94 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None -2.3214 2.4267 -3.8975 N\\n2 None -0.8631 2.0781 -3.8975 C\\n3 None -0.0811 3.3587 -3.8975 C\\n4 None -1.0561 4.4976 -3.8975 O\\n5 None -2.4408 3.9226 -3.8975 C\\n6 None -3.7214 4.7031 -3.8975 C\\n7 None -5.0394 3.9851 -3.8975 C\\n8 None -6.3936 4.6309 -3.8975 O\\n9 None -7.4242 3.5406 -3.8975 C\\n10 None -6.7061 2.2226 -3.8975 C\\n11 None -5.2325 2.4976 -3.8975 N\\n12 None -7.0283 1.5455 -5.1963 C\\n13 None -0.5749 1.3858 -2.5985 C\\n14 None -1.6301 0.5403 -1.9490 C\\n15 None -1.3432 -0.1523 -0.6505 C\\n16 None 0.0000 0.0000 0.0000 C\\n17 None 1.0565 0.8457 -0.6491 C\\n18 None 0.7683 1.5381 -1.9480 C\\n19 None -8.3629 1.7649 -5.8463 C\\n20 None -8.6836 1.0868 -7.1457 C\\n21 None -7.6725 0.1905 -7.7949 C\\n22 None -6.3380 -0.0290 -7.1448 C\\n23 None -6.0160 0.6489 -5.8450 C\\n24 None -7.4242 3.5406 -5.3764 H\\n25 None -0.0811 3.3587 -2.4399 H\\n26 None -3.5881 1.1684 -3.8975 Cu\\n27 None -3.5881 1.1684 -2.0307 Cl\\n28 None -4.3976 0.6992 -5.7072 Cl\\n29 None -8.5061 2.4601 -3.8975 H\\n30 None 0.9717 2.3059 -3.8975 H\\n31 None -3.0032 5.2937 -2.7204 C\\n32 None -3.7214 4.7031 -5.3975 C\\n33 None -5.6354 -4.1991 -10.0483 C\\n34 None -6.6762 -3.7043 -11.0080 C\\n35 None -5.3807 -3.4566 -8.7705 C\\n36 None -6.1668 -2.2193 -8.4524 C\\n37 None -7.2076 -1.7245 -9.4121 C\\n38 None -7.4622 -2.4671 -10.6898 C\\n39 None -7.9937 -0.4873 -9.0939 C\\n40 None -8.5037 -1.9724 -11.6507 C\\n41 None -4.8493 -5.4364 -10.3665 C\\n42 None -3.8085 -5.9311 -9.4068 F\\n43 None -5.8846 -6.2720 -9.6745 F\\n44 None -4.5946 -4.6939 -9.0887 F\\n45 None -8.7584 -2.7149 -12.9284 F\\n46 None -9.2898 -0.7351 -11.3325 F\\n47 None -9.5390 -2.8081 -10.9587 F\\n48 None 3.8337 -3.4633 1.3435 C\\n49 None 3.0140 -3.2741 2.5850 C\\n50 None 3.4715 -2.7288 0.0872 C\\n51 None 2.2897 -1.8052 0.0724 C\\n52 None 1.4700 -1.6160 1.3139 C\\n53 None 1.8322 -2.3505 2.5702 C\\n54 None 0.2882 -0.6924 1.2990 C\\n55 None 1.0123 -2.1616 3.8130 C\\n56 None 5.0155 -4.3869 1.3583 C\\n57 None 5.8351 -4.5761 0.1168 F\\n58 None 5.9004 -3.2480 1.7690 F\\n59 None 4.6533 -3.6524 0.1020 F\\n60 None 1.3745 -2.8961 5.0693 F\\n61 None -0.1695 -1.2380 3.7982 F\\n62 None 1.8972 -1.0227 4.2237 F\\n63 None -0.6071 1.4629 -4.7347 H\\n64 None -6.9925 1.6208 -3.0604 H\\n65 None -2.5884 0.4312 -2.4123 H\\n66 None -2.0967 -0.7551 -0.1882 H\\n67 None 2.0149 0.9550 -0.1859 H\\n68 None 1.5214 2.1410 -2.4109 H\\n69 None -9.0853 2.4045 -5.3837 H\\n70 None -9.6349 1.2426 -7.6101 H\\n71 None -5.6161 -0.6687 -7.6080 H\\n72 None -5.0647 0.4931 -5.3807 H\\n73 None -2.8977 4.5509 -1.9576 H\\n74 None -3.5648 6.1204 -2.3381 H\\n75 None -2.0349 5.6312 -3.0260 H\\n76 None -2.7126 4.7031 -5.7542 H\\n77 None -4.2258 5.5768 -5.7542 H\\n78 None -4.2258 3.8295 -5.7542 H\\n79 None -6.8579 -4.2341 -11.9197 H\\n80 None -4.6381 -3.8096 -8.0858 H\\n81 None -5.9851 -1.6895 -7.5407 H\\n82 None -7.8182 0.2183 -9.8790 H\\n83 None -9.0285 -0.7586 -9.0701 H\\n84 None 3.2724 -3.7982 3.4814 H\\n85 None 4.0563 -2.8638 -0.7986 H\\n86 None 2.0313 -1.2812 -0.8240 H\\n87 None -0.5758 -1.2684 1.5573 H\\n88 None 0.4587 0.0630 2.0375 H\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 9 24 1\\n28 3 25 1\\n29 11 26 1\\n30 26 1 1\\n31 26 27 1\\n32 26 28 1\\n33 9 29 1\\n34 3 30 1\\n35 6 31 1\\n36 6 32 1\\n37 33 34 2\\n38 33 35 1\\n39 35 36 2\\n40 36 37 1\\n41 37 38 2\\n42 38 34 1\\n43 37 39 1\\n44 38 40 1\\n45 33 41 1\\n46 41 42 1\\n47 41 43 1\\n48 41 44 1\\n49 40 45 1\\n50 40 46 1\\n51 40 47 1\\n52 21 39 1\\n53 48 49 2\\n54 48 50 1\\n55 50 51 2\\n56 51 52 1\\n57 52 53 2\\n58 53 49 1\\n59 52 54 1\\n60 53 55 1\\n61 48 56 1\\n62 56 57 1\\n63 56 58 1\\n64 56 59 1\\n65 55 60 1\\n66 55 61 1\\n67 55 62 1\\n68 16 54 1\\n69 2 63 1\\n70 10 64 1\\n71 14 65 1\\n72 15 66 1\\n73 17 67 1\\n74 18 68 1\\n75 19 69 1\\n76 20 70 1\\n77 22 71 1\\n78 23 72 1\\n79 31 73 1\\n80 31 74 1\\n81 31 75 1\\n82 32 76 1\\n83 32 77 1\\n84 32 78 1\\n85 34 79 1\\n86 35 80 1\\n87 36 81 1\\n88 39 82 1\\n89 39 83 1\\n90 49 84 1\\n91 50 85 1\\n92 51 86 1\\n93 54 87 1\\n94 54 88 1\\n\\n\",\"mol2\");\n",
       "\tviewer_17295508781583483.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n",
       "\tviewer_17295508781583483.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n",
       "\tviewer_17295508781583483.zoomTo();\n",
       "\tviewer_17295508781583483.setBackgroundColor(\"white\");\n",
       "viewer_17295508781583483.render();\n",
       "});\n",
       "</script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<script>\n            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n                \n                viewer_17295508781583483.render();\n            });\n            </script>",
      "text/html": [
       "<script>\n",
       "            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n",
       "                \n",
       "                viewer_17295508781583483.render();\n",
       "            });\n",
       "            </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Molecule(name='410_1_1_Me', formula='C39 H30 Cl2 Cu1 F12 N2 O2')"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# finally, we'll do an optimization with XTB gfn2 to clean up our geometries a bit\n",
    "\n",
    "for mol in fully_expanded_mols:\n",
    "    mol.add_implicit_hydrogens()\n",
    "\n",
    "mol"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example 1: Parallel Openbabel Optimization \n",
    "\n",
    "Example of optimization using the built in functionality with `openbabel` optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Parallel(n_jobs=32)]: Using backend ThreadingBackend with 32 concurrent workers.\n",
      "[Parallel(n_jobs=32)]: Done   1 tasks      | elapsed:    1.0s\n",
      "[Parallel(n_jobs=32)]: Done   2 out of  12 | elapsed:    1.8s remaining:    9.1s\n",
      "[Parallel(n_jobs=32)]: Done   3 out of  12 | elapsed:    2.7s remaining:    8.1s\n",
      "[Parallel(n_jobs=32)]: Done   4 out of  12 | elapsed:    3.7s remaining:    7.4s\n",
      "[Parallel(n_jobs=32)]: Done   5 out of  12 | elapsed:    4.6s remaining:    6.5s\n",
      "[Parallel(n_jobs=32)]: Done   6 out of  12 | elapsed:    5.6s remaining:    5.6s\n",
      "[Parallel(n_jobs=32)]: Done   7 out of  12 | elapsed:    7.1s remaining:    5.1s\n",
      "[Parallel(n_jobs=32)]: Done   8 out of  12 | elapsed:    9.9s remaining:    5.0s\n",
      "[Parallel(n_jobs=32)]: Done   9 out of  12 | elapsed:    9.9s remaining:    3.3s\n",
      "[Parallel(n_jobs=32)]: Done  10 out of  12 | elapsed:   11.4s remaining:    2.3s\n",
      "[Parallel(n_jobs=32)]: Done  12 out of  12 | elapsed:   15.2s finished\n"
     ]
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<div id=\"3dmolviewer_17295512967711878\"  style=\"position: relative; width: 100%; height: 500px;\">\n        <p id=\"3dmolwarning_17295512967711878\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n        </div>\n<script>\n\nvar loadScriptAsync = function(uri){\n  return new Promise((resolve, reject) => {\n    //this is to ignore the existence of requirejs amd\n    var savedexports, savedmodule;\n    if (typeof exports !== 'undefined') savedexports = exports;\n    else exports = {}\n    if (typeof module !== 'undefined') savedmodule = module;\n    else module = {}\n\n    var tag = document.createElement('script');\n    tag.src = uri;\n    tag.async = true;\n    tag.onload = () => {\n        exports = savedexports;\n        module = savedmodule;\n        resolve();\n    };\n  var firstScriptTag = document.getElementsByTagName('script')[0];\n  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n});\n};\n\nif(typeof $3Dmolpromise === 'undefined') {\n$3Dmolpromise = null;\n  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n}\n\nvar viewer_17295512967711878 = null;\nvar warn = document.getElementById(\"3dmolwarning_17295512967711878\");\nif(warn) {\n    warn.parentNode.removeChild(warn);\n}\n$3Dmolpromise.then(function() {\nviewer_17295512967711878 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295512967711878\"),{backgroundColor:\"white\"});\nviewer_17295512967711878.zoomTo();\n\tviewer_17295512967711878.addModel(\"@<TRIPOS>MOLECULE\\n408_1_1_MeTol\\n150 158 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None -1.8666 2.9336 -3.4311 N\\n2 None -0.4412 2.5964 -3.0616 C\\n3 None 0.2951 3.9372 -3.1622 C\\n4 None -0.5983 4.7279 -3.9418 O\\n5 None -1.8810 4.2415 -3.9459 C\\n6 None -3.0010 5.0479 -3.5023 C\\n7 None -4.0720 4.1621 -3.0878 C\\n8 None -5.3301 4.6334 -2.8278 O\\n9 None -6.3023 3.8922 -3.5526 C\\n10 None -5.5880 2.5557 -3.8426 C\\n11 None -4.1174 2.8990 -3.6938 N\\n12 None -6.1609 1.8912 -5.1271 C\\n13 None -0.1075 1.8807 -1.7370 C\\n14 None -1.0368 1.1631 -0.9707 C\\n15 None -0.6384 0.4701 0.1739 C\\n16 None 0.6943 0.4887 0.5890 C\\n17 None 1.6196 1.2166 -0.1538 C\\n18 None 1.2260 1.8880 -1.3064 C\\n19 None -7.4761 2.1785 -5.5347 C\\n20 None -8.0713 1.5228 -6.6107 C\\n21 None -7.3794 0.5430 -7.3171 C\\n22 None -6.0634 0.2699 -6.9496 C\\n23 None -5.4813 0.9049 -5.8573 C\\n24 None -6.5055 4.4375 -4.4790 H\\n25 None 0.4013 4.4047 -2.1797 H\\n26 None -2.9806 2.6204 -3.6108 Cu\\n27 None -2.9318 1.5168 -3.7804 Cl\\n28 None -2.9301 1.5177 -3.7850 Cl\\n29 None -7.2139 3.7681 -2.9618 H\\n30 None 1.2626 3.8441 -3.6627 H\\n31 None -3.4726 8.3384 -2.7787 C\\n32 None -2.5877 7.4359 -2.1735 C\\n33 None -1.5851 7.9575 -1.3468 C\\n34 None -1.4215 9.3305 -1.1864 C\\n35 None -2.2504 10.2191 -1.8662 C\\n36 None -3.2811 9.7145 -2.6573 C\\n37 None -2.7106 5.9044 -2.2388 C\\n38 None -2.0523 11.7176 -1.7222 C\\n39 None -1.4039 7.3943 -5.0849 C\\n40 None -2.5145 6.7033 -5.5874 C\\n41 None -2.8393 6.8881 -6.9367 C\\n42 None -2.1243 7.7769 -7.7382 C\\n43 None -1.0720 8.5163 -7.2022 C\\n44 None -0.7052 8.3051 -5.8751 C\\n45 None -3.4601 5.8194 -4.7466 C\\n46 None -0.3564 9.5602 -8.0427 C\\n47 None -7.7343 -1.6784 -8.6281 C\\n48 None -7.3022 -2.4658 -7.5580 C\\n49 None -6.8231 -3.7643 -7.7682 C\\n50 None -6.9059 -4.2960 -9.0606 C\\n51 None -7.4384 -3.5700 -10.1325 C\\n52 None -7.8218 -2.2440 -9.8990 C\\n53 None -8.0665 -0.1925 -8.4677 C\\n54 None -6.0710 -4.5505 -6.6711 C\\n55 None -7.4669 -4.1931 -11.5455 C\\n56 None -7.9785 -5.6597 -11.5119 C\\n57 None -8.3904 -3.4306 -12.5347 C\\n58 None -6.0313 -4.1780 -12.1221 C\\n59 None -6.5969 -6.0043 -6.5382 C\\n60 None -6.1675 -3.9068 -5.2610 C\\n61 None -4.5703 -4.5937 -7.0549 C\\n62 None 1.0200 -1.7543 1.8612 C\\n63 None 0.7450 -2.4971 0.7105 C\\n64 None 0.5527 -3.8839 0.7761 C\\n65 None 0.6611 -4.5059 2.0275 C\\n66 None 0.9866 -3.7951 3.1893 C\\n67 None 1.1567 -2.4105 3.0822 C\\n68 None 1.1377 -0.2308 1.8578 C\\n69 None 0.0891 -4.6940 -0.4573 C\\n70 None 1.0152 -4.5118 4.5586 C\\n71 None 1.7056 -5.9017 4.4795 C\\n72 None 1.7734 -3.7126 5.6546 C\\n73 None -0.4441 -4.7081 5.0328 C\\n74 None 0.6715 -6.1354 -0.4785 C\\n75 None 0.4974 -4.0411 -1.8067 C\\n76 None -1.4545 -4.7895 -0.4156 C\\n77 None -0.0600 1.9682 -3.8722 H\\n78 None -5.8246 1.8918 -3.0058 H\\n79 None -2.0823 1.1177 -1.2466 H\\n80 None -1.3746 -0.0944 0.7414 H\\n81 None 2.6597 1.2628 0.1602 H\\n82 None 1.9851 2.4224 -1.8712 H\\n83 None -8.0865 2.9033 -5.0044 H\\n84 None -9.0924 1.7742 -6.8877 H\\n85 None -5.4875 -0.4817 -7.4834 H\\n86 None -4.4956 0.5672 -5.5932 H\\n87 None -4.3257 7.9997 -3.3483 H\\n88 None -0.9265 7.2887 -0.7975 H\\n89 None -0.6422 9.7040 -0.5262 H\\n90 None -3.9531 10.3966 -3.1728 H\\n91 None -1.7919 5.5070 -1.8024 H\\n92 None -3.4398 5.6795 -1.4555 H\\n93 None -1.0435 11.9462 -1.3702 H\\n94 None -2.7672 12.1293 -1.0065 H\\n95 None -2.1959 12.2184 -2.6823 H\\n96 None -1.0646 7.2544 -4.0697 H\\n97 None -3.6793 6.3519 -7.3720 H\\n98 None -2.4110 7.9130 -8.7785 H\\n99 None 0.1207 8.8649 -5.4424 H\\n100 None -4.3730 6.3746 -4.5485 H\\n101 None -3.8110 5.0578 -5.4504 H\\n102 None 0.6629 9.7222 -7.6847 H\\n103 None -0.8910 10.5118 -7.9906 H\\n104 None -0.3060 9.2530 -9.0896 H\\n105 None -7.2732 -2.0245 -6.5683 H\\n106 None -6.5031 -5.2856 -9.2448 H\\n107 None -8.1704 -1.6145 -10.7111 H\\n108 None -7.7927 0.3269 -9.3897 H\\n109 None -9.1498 -0.0921 -8.3713 H\\n110 None -7.2926 -6.3203 -10.9787 H\\n111 None -8.0814 -6.0603 -12.5237 H\\n112 None -8.9557 -5.7163 -11.0262 H\\n113 None -8.4358 -3.9424 -13.4994 H\\n114 None -8.0239 -2.4203 -12.7288 H\\n115 None -9.4085 -3.3635 -12.1427 H\\n116 None -5.3494 -4.7467 -11.4853 H\\n117 None -5.6554 -3.1538 -12.1863 H\\n118 None -6.0044 -4.6148 -13.1232 H\\n119 None -6.0398 -6.5468 -5.7697 H\\n120 None -6.4890 -6.5654 -7.4679 H\\n121 None -7.6524 -6.0095 -6.2568 H\\n122 None -5.6405 -4.5130 -4.5197 H\\n123 None -7.2090 -3.8199 -4.9419 H\\n124 None -5.7135 -2.9128 -5.2463 H\\n125 None -3.9795 -5.1018 -6.2893 H\\n126 None -4.1772 -3.5800 -7.1701 H\\n127 None -4.4192 -5.1201 -8.0003 H\\n128 None 0.6400 -1.9762 -0.2337 H\\n129 None 0.4437 -5.5630 2.1103 H\\n130 None 1.3636 -1.8059 3.9591 H\\n131 None 0.5427 0.1615 2.6863 H\\n132 None 2.1742 0.0318 2.0830 H\\n133 None 2.7176 -5.8088 4.0782 H\\n134 None 1.1498 -6.6017 3.8537 H\\n135 None 1.7775 -6.3564 5.4711 H\\n136 None 2.7930 -3.4845 5.3338 H\\n137 None 1.8345 -4.2854 6.5835 H\\n138 None 1.2653 -2.7763 5.8946 H\\n139 None -1.0086 -5.3076 4.3144 H\\n140 None -0.9470 -3.7428 5.1326 H\\n141 None -0.4805 -5.2134 6.0008 H\\n142 None 1.7618 -6.1145 -0.4118 H\\n143 None 0.4007 -6.6513 -1.4035 H\\n144 None 0.2866 -6.7458 0.3403 H\\n145 None 1.5767 -3.8746 -1.8462 H\\n146 None -0.0096 -3.0870 -1.9644 H\\n147 None 0.2257 -4.6835 -2.6484 H\\n148 None -1.8397 -5.3475 -1.2723 H\\n149 None -1.9010 -3.7919 -0.4289 H\\n150 None -1.7864 -5.2930 0.4959 H\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 9 24 1\\n28 3 25 1\\n29 11 26 1\\n30 26 1 1\\n31 26 27 1\\n32 26 28 1\\n33 9 29 1\\n34 3 30 1\\n35 31 32 2\\n36 32 33 1\\n37 33 34 2\\n38 34 35 1\\n39 35 36 2\\n40 36 31 1\\n41 32 37 1\\n42 35 38 1\\n43 6 37 1\\n44 39 40 2\\n45 40 41 1\\n46 41 42 2\\n47 42 43 1\\n48 43 44 2\\n49 44 39 1\\n50 40 45 1\\n51 43 46 1\\n52 6 45 1\\n53 47 48 2\\n54 48 49 1\\n55 49 50 2\\n56 50 51 1\\n57 51 52 2\\n58 52 47 1\\n59 47 53 1\\n60 49 54 1\\n61 51 55 1\\n62 55 56 1\\n63 55 57 1\\n64 55 58 1\\n65 54 59 1\\n66 54 60 1\\n67 54 61 1\\n68 21 53 1\\n69 62 63 2\\n70 63 64 1\\n71 64 65 2\\n72 65 66 1\\n73 66 67 2\\n74 67 62 1\\n75 62 68 1\\n76 64 69 1\\n77 66 70 1\\n78 70 71 1\\n79 70 72 1\\n80 70 73 1\\n81 69 74 1\\n82 69 75 1\\n83 69 76 1\\n84 16 68 1\\n85 2 77 1\\n86 10 78 1\\n87 14 79 1\\n88 15 80 1\\n89 17 81 1\\n90 18 82 1\\n91 19 83 1\\n92 20 84 1\\n93 22 85 1\\n94 23 86 1\\n95 31 87 1\\n96 33 88 1\\n97 34 89 1\\n98 36 90 1\\n99 37 91 1\\n100 37 92 1\\n101 38 93 1\\n102 38 94 1\\n103 38 95 1\\n104 39 96 1\\n105 41 97 1\\n106 42 98 1\\n107 44 99 1\\n108 45 100 1\\n109 45 101 1\\n110 46 102 1\\n111 46 103 1\\n112 46 104 1\\n113 48 105 1\\n114 50 106 1\\n115 52 107 1\\n116 53 108 1\\n117 53 109 1\\n118 56 110 1\\n119 56 111 1\\n120 56 112 1\\n121 57 113 1\\n122 57 114 1\\n123 57 115 1\\n124 58 116 1\\n125 58 117 1\\n126 58 118 1\\n127 59 119 1\\n128 59 120 1\\n129 59 121 1\\n130 60 122 1\\n131 60 123 1\\n132 60 124 1\\n133 61 125 1\\n134 61 126 1\\n135 61 127 1\\n136 63 128 1\\n137 65 129 1\\n138 67 130 1\\n139 68 131 1\\n140 68 132 1\\n141 71 133 1\\n142 71 134 1\\n143 71 135 1\\n144 72 136 1\\n145 72 137 1\\n146 72 138 1\\n147 73 139 1\\n148 73 140 1\\n149 73 141 1\\n150 74 142 1\\n151 74 143 1\\n152 74 144 1\\n153 75 145 1\\n154 75 146 1\\n155 75 147 1\\n156 76 148 1\\n157 76 149 1\\n158 76 150 1\\n\\n\",\"mol2\");\n\tviewer_17295512967711878.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n\tviewer_17295512967711878.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n\tviewer_17295512967711878.zoomTo();\n\tviewer_17295512967711878.setBackgroundColor(\"white\");\nviewer_17295512967711878.render();\n});\n</script>",
      "text/html": [
       "<div id=\"3dmolviewer_17295512967711878\"  style=\"position: relative; width: 100%; height: 500px;\">\n",
       "        <p id=\"3dmolwarning_17295512967711878\" style=\"background-color:#ffcccc;color:black\">You appear to be running in JupyterLab (or JavaScript failed to load for some other reason).  You need to install the 3dmol extension: <br>\n",
       "        <tt>jupyter labextension install jupyterlab_3dmol</tt></p>\n",
       "        </div>\n",
       "<script>\n",
       "\n",
       "var loadScriptAsync = function(uri){\n",
       "  return new Promise((resolve, reject) => {\n",
       "    //this is to ignore the existence of requirejs amd\n",
       "    var savedexports, savedmodule;\n",
       "    if (typeof exports !== 'undefined') savedexports = exports;\n",
       "    else exports = {}\n",
       "    if (typeof module !== 'undefined') savedmodule = module;\n",
       "    else module = {}\n",
       "\n",
       "    var tag = document.createElement('script');\n",
       "    tag.src = uri;\n",
       "    tag.async = true;\n",
       "    tag.onload = () => {\n",
       "        exports = savedexports;\n",
       "        module = savedmodule;\n",
       "        resolve();\n",
       "    };\n",
       "  var firstScriptTag = document.getElementsByTagName('script')[0];\n",
       "  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n",
       "});\n",
       "};\n",
       "\n",
       "if(typeof $3Dmolpromise === 'undefined') {\n",
       "$3Dmolpromise = null;\n",
       "  $3Dmolpromise = loadScriptAsync('https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.4/3Dmol-min.js');\n",
       "}\n",
       "\n",
       "var viewer_17295512967711878 = null;\n",
       "var warn = document.getElementById(\"3dmolwarning_17295512967711878\");\n",
       "if(warn) {\n",
       "    warn.parentNode.removeChild(warn);\n",
       "}\n",
       "$3Dmolpromise.then(function() {\n",
       "viewer_17295512967711878 = $3Dmol.createViewer(document.getElementById(\"3dmolviewer_17295512967711878\"),{backgroundColor:\"white\"});\n",
       "viewer_17295512967711878.zoomTo();\n",
       "\tviewer_17295512967711878.addModel(\"@<TRIPOS>MOLECULE\\n408_1_1_MeTol\\n150 158 0 0 0\\nSMALL\\nNO_CHARGES\\n\\n@<TRIPOS>ATOM\\n1 None -1.8666 2.9336 -3.4311 N\\n2 None -0.4412 2.5964 -3.0616 C\\n3 None 0.2951 3.9372 -3.1622 C\\n4 None -0.5983 4.7279 -3.9418 O\\n5 None -1.8810 4.2415 -3.9459 C\\n6 None -3.0010 5.0479 -3.5023 C\\n7 None -4.0720 4.1621 -3.0878 C\\n8 None -5.3301 4.6334 -2.8278 O\\n9 None -6.3023 3.8922 -3.5526 C\\n10 None -5.5880 2.5557 -3.8426 C\\n11 None -4.1174 2.8990 -3.6938 N\\n12 None -6.1609 1.8912 -5.1271 C\\n13 None -0.1075 1.8807 -1.7370 C\\n14 None -1.0368 1.1631 -0.9707 C\\n15 None -0.6384 0.4701 0.1739 C\\n16 None 0.6943 0.4887 0.5890 C\\n17 None 1.6196 1.2166 -0.1538 C\\n18 None 1.2260 1.8880 -1.3064 C\\n19 None -7.4761 2.1785 -5.5347 C\\n20 None -8.0713 1.5228 -6.6107 C\\n21 None -7.3794 0.5430 -7.3171 C\\n22 None -6.0634 0.2699 -6.9496 C\\n23 None -5.4813 0.9049 -5.8573 C\\n24 None -6.5055 4.4375 -4.4790 H\\n25 None 0.4013 4.4047 -2.1797 H\\n26 None -2.9806 2.6204 -3.6108 Cu\\n27 None -2.9318 1.5168 -3.7804 Cl\\n28 None -2.9301 1.5177 -3.7850 Cl\\n29 None -7.2139 3.7681 -2.9618 H\\n30 None 1.2626 3.8441 -3.6627 H\\n31 None -3.4726 8.3384 -2.7787 C\\n32 None -2.5877 7.4359 -2.1735 C\\n33 None -1.5851 7.9575 -1.3468 C\\n34 None -1.4215 9.3305 -1.1864 C\\n35 None -2.2504 10.2191 -1.8662 C\\n36 None -3.2811 9.7145 -2.6573 C\\n37 None -2.7106 5.9044 -2.2388 C\\n38 None -2.0523 11.7176 -1.7222 C\\n39 None -1.4039 7.3943 -5.0849 C\\n40 None -2.5145 6.7033 -5.5874 C\\n41 None -2.8393 6.8881 -6.9367 C\\n42 None -2.1243 7.7769 -7.7382 C\\n43 None -1.0720 8.5163 -7.2022 C\\n44 None -0.7052 8.3051 -5.8751 C\\n45 None -3.4601 5.8194 -4.7466 C\\n46 None -0.3564 9.5602 -8.0427 C\\n47 None -7.7343 -1.6784 -8.6281 C\\n48 None -7.3022 -2.4658 -7.5580 C\\n49 None -6.8231 -3.7643 -7.7682 C\\n50 None -6.9059 -4.2960 -9.0606 C\\n51 None -7.4384 -3.5700 -10.1325 C\\n52 None -7.8218 -2.2440 -9.8990 C\\n53 None -8.0665 -0.1925 -8.4677 C\\n54 None -6.0710 -4.5505 -6.6711 C\\n55 None -7.4669 -4.1931 -11.5455 C\\n56 None -7.9785 -5.6597 -11.5119 C\\n57 None -8.3904 -3.4306 -12.5347 C\\n58 None -6.0313 -4.1780 -12.1221 C\\n59 None -6.5969 -6.0043 -6.5382 C\\n60 None -6.1675 -3.9068 -5.2610 C\\n61 None -4.5703 -4.5937 -7.0549 C\\n62 None 1.0200 -1.7543 1.8612 C\\n63 None 0.7450 -2.4971 0.7105 C\\n64 None 0.5527 -3.8839 0.7761 C\\n65 None 0.6611 -4.5059 2.0275 C\\n66 None 0.9866 -3.7951 3.1893 C\\n67 None 1.1567 -2.4105 3.0822 C\\n68 None 1.1377 -0.2308 1.8578 C\\n69 None 0.0891 -4.6940 -0.4573 C\\n70 None 1.0152 -4.5118 4.5586 C\\n71 None 1.7056 -5.9017 4.4795 C\\n72 None 1.7734 -3.7126 5.6546 C\\n73 None -0.4441 -4.7081 5.0328 C\\n74 None 0.6715 -6.1354 -0.4785 C\\n75 None 0.4974 -4.0411 -1.8067 C\\n76 None -1.4545 -4.7895 -0.4156 C\\n77 None -0.0600 1.9682 -3.8722 H\\n78 None -5.8246 1.8918 -3.0058 H\\n79 None -2.0823 1.1177 -1.2466 H\\n80 None -1.3746 -0.0944 0.7414 H\\n81 None 2.6597 1.2628 0.1602 H\\n82 None 1.9851 2.4224 -1.8712 H\\n83 None -8.0865 2.9033 -5.0044 H\\n84 None -9.0924 1.7742 -6.8877 H\\n85 None -5.4875 -0.4817 -7.4834 H\\n86 None -4.4956 0.5672 -5.5932 H\\n87 None -4.3257 7.9997 -3.3483 H\\n88 None -0.9265 7.2887 -0.7975 H\\n89 None -0.6422 9.7040 -0.5262 H\\n90 None -3.9531 10.3966 -3.1728 H\\n91 None -1.7919 5.5070 -1.8024 H\\n92 None -3.4398 5.6795 -1.4555 H\\n93 None -1.0435 11.9462 -1.3702 H\\n94 None -2.7672 12.1293 -1.0065 H\\n95 None -2.1959 12.2184 -2.6823 H\\n96 None -1.0646 7.2544 -4.0697 H\\n97 None -3.6793 6.3519 -7.3720 H\\n98 None -2.4110 7.9130 -8.7785 H\\n99 None 0.1207 8.8649 -5.4424 H\\n100 None -4.3730 6.3746 -4.5485 H\\n101 None -3.8110 5.0578 -5.4504 H\\n102 None 0.6629 9.7222 -7.6847 H\\n103 None -0.8910 10.5118 -7.9906 H\\n104 None -0.3060 9.2530 -9.0896 H\\n105 None -7.2732 -2.0245 -6.5683 H\\n106 None -6.5031 -5.2856 -9.2448 H\\n107 None -8.1704 -1.6145 -10.7111 H\\n108 None -7.7927 0.3269 -9.3897 H\\n109 None -9.1498 -0.0921 -8.3713 H\\n110 None -7.2926 -6.3203 -10.9787 H\\n111 None -8.0814 -6.0603 -12.5237 H\\n112 None -8.9557 -5.7163 -11.0262 H\\n113 None -8.4358 -3.9424 -13.4994 H\\n114 None -8.0239 -2.4203 -12.7288 H\\n115 None -9.4085 -3.3635 -12.1427 H\\n116 None -5.3494 -4.7467 -11.4853 H\\n117 None -5.6554 -3.1538 -12.1863 H\\n118 None -6.0044 -4.6148 -13.1232 H\\n119 None -6.0398 -6.5468 -5.7697 H\\n120 None -6.4890 -6.5654 -7.4679 H\\n121 None -7.6524 -6.0095 -6.2568 H\\n122 None -5.6405 -4.5130 -4.5197 H\\n123 None -7.2090 -3.8199 -4.9419 H\\n124 None -5.7135 -2.9128 -5.2463 H\\n125 None -3.9795 -5.1018 -6.2893 H\\n126 None -4.1772 -3.5800 -7.1701 H\\n127 None -4.4192 -5.1201 -8.0003 H\\n128 None 0.6400 -1.9762 -0.2337 H\\n129 None 0.4437 -5.5630 2.1103 H\\n130 None 1.3636 -1.8059 3.9591 H\\n131 None 0.5427 0.1615 2.6863 H\\n132 None 2.1742 0.0318 2.0830 H\\n133 None 2.7176 -5.8088 4.0782 H\\n134 None 1.1498 -6.6017 3.8537 H\\n135 None 1.7775 -6.3564 5.4711 H\\n136 None 2.7930 -3.4845 5.3338 H\\n137 None 1.8345 -4.2854 6.5835 H\\n138 None 1.2653 -2.7763 5.8946 H\\n139 None -1.0086 -5.3076 4.3144 H\\n140 None -0.9470 -3.7428 5.1326 H\\n141 None -0.4805 -5.2134 6.0008 H\\n142 None 1.7618 -6.1145 -0.4118 H\\n143 None 0.4007 -6.6513 -1.4035 H\\n144 None 0.2866 -6.7458 0.3403 H\\n145 None 1.5767 -3.8746 -1.8462 H\\n146 None -0.0096 -3.0870 -1.9644 H\\n147 None 0.2257 -4.6835 -2.6484 H\\n148 None -1.8397 -5.3475 -1.2723 H\\n149 None -1.9010 -3.7919 -0.4289 H\\n150 None -1.7864 -5.2930 0.4959 H\\n@<TRIPOS>BOND\\n1 1 2 1\\n2 2 3 1\\n3 3 4 1\\n4 4 5 1\\n5 5 1 2\\n6 5 6 1\\n7 6 7 1\\n8 7 8 1\\n9 8 9 1\\n10 9 10 1\\n11 10 11 1\\n12 11 7 2\\n13 10 12 1\\n14 2 13 1\\n15 13 14 2\\n16 14 15 1\\n17 15 16 2\\n18 16 17 1\\n19 17 18 2\\n20 18 13 1\\n21 12 19 2\\n22 19 20 1\\n23 20 21 2\\n24 21 22 1\\n25 22 23 2\\n26 23 12 1\\n27 9 24 1\\n28 3 25 1\\n29 11 26 1\\n30 26 1 1\\n31 26 27 1\\n32 26 28 1\\n33 9 29 1\\n34 3 30 1\\n35 31 32 2\\n36 32 33 1\\n37 33 34 2\\n38 34 35 1\\n39 35 36 2\\n40 36 31 1\\n41 32 37 1\\n42 35 38 1\\n43 6 37 1\\n44 39 40 2\\n45 40 41 1\\n46 41 42 2\\n47 42 43 1\\n48 43 44 2\\n49 44 39 1\\n50 40 45 1\\n51 43 46 1\\n52 6 45 1\\n53 47 48 2\\n54 48 49 1\\n55 49 50 2\\n56 50 51 1\\n57 51 52 2\\n58 52 47 1\\n59 47 53 1\\n60 49 54 1\\n61 51 55 1\\n62 55 56 1\\n63 55 57 1\\n64 55 58 1\\n65 54 59 1\\n66 54 60 1\\n67 54 61 1\\n68 21 53 1\\n69 62 63 2\\n70 63 64 1\\n71 64 65 2\\n72 65 66 1\\n73 66 67 2\\n74 67 62 1\\n75 62 68 1\\n76 64 69 1\\n77 66 70 1\\n78 70 71 1\\n79 70 72 1\\n80 70 73 1\\n81 69 74 1\\n82 69 75 1\\n83 69 76 1\\n84 16 68 1\\n85 2 77 1\\n86 10 78 1\\n87 14 79 1\\n88 15 80 1\\n89 17 81 1\\n90 18 82 1\\n91 19 83 1\\n92 20 84 1\\n93 22 85 1\\n94 23 86 1\\n95 31 87 1\\n96 33 88 1\\n97 34 89 1\\n98 36 90 1\\n99 37 91 1\\n100 37 92 1\\n101 38 93 1\\n102 38 94 1\\n103 38 95 1\\n104 39 96 1\\n105 41 97 1\\n106 42 98 1\\n107 44 99 1\\n108 45 100 1\\n109 45 101 1\\n110 46 102 1\\n111 46 103 1\\n112 46 104 1\\n113 48 105 1\\n114 50 106 1\\n115 52 107 1\\n116 53 108 1\\n117 53 109 1\\n118 56 110 1\\n119 56 111 1\\n120 56 112 1\\n121 57 113 1\\n122 57 114 1\\n123 57 115 1\\n124 58 116 1\\n125 58 117 1\\n126 58 118 1\\n127 59 119 1\\n128 59 120 1\\n129 59 121 1\\n130 60 122 1\\n131 60 123 1\\n132 60 124 1\\n133 61 125 1\\n134 61 126 1\\n135 61 127 1\\n136 63 128 1\\n137 65 129 1\\n138 67 130 1\\n139 68 131 1\\n140 68 132 1\\n141 71 133 1\\n142 71 134 1\\n143 71 135 1\\n144 72 136 1\\n145 72 137 1\\n146 72 138 1\\n147 73 139 1\\n148 73 140 1\\n149 73 141 1\\n150 74 142 1\\n151 74 143 1\\n152 74 144 1\\n153 75 145 1\\n154 75 146 1\\n155 75 147 1\\n156 76 148 1\\n157 76 149 1\\n158 76 150 1\\n\\n\",\"mol2\");\n",
       "\tviewer_17295512967711878.setStyle({\"stick\": {\"radius\": 0.1}, \"sphere\": {\"scale\": 0.15}});\n",
       "\tviewer_17295512967711878.setHoverable({},true,\"\\n        function(atom,viewer,event,container) {\\n            if(!atom.label) {\\n                atom.label = viewer.addLabel(atom.elem + '(' + atom.index + ')', {position: atom, backgroundColor: 'silver', fontColor:'black'});\\n            }\\n        }\\n        \",\"\\n        function(atom,viewer) { \\n            if(atom.label) {\\n                viewer.removeLabel(atom.label);\\n                delete atom.label;\\n            }\\n        }\\n        \");\n",
       "\tviewer_17295512967711878.zoomTo();\n",
       "\tviewer_17295512967711878.setBackgroundColor(\"white\");\n",
       "viewer_17295512967711878.render();\n",
       "});\n",
       "</script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/3dmoljs_load.v0": "<script>\n            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n                \n                viewer_17295512967711878.render();\n            });\n            </script>",
      "text/html": [
       "<script>\n",
       "            $3Dmolpromise.then(function() { //wrap in promise for non-interactive functionality\n",
       "                \n",
       "                viewer_17295512967711878.render();\n",
       "            });\n",
       "            </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Molecule(name='408_1_1_MeTol', formula='C65 H78 Cl2 Cu1 N2 O2')"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from joblib import delayed, Parallel\n",
    "from molli.external import openbabel as mob\n",
    "\n",
    "# Sets up and runs parallel calculation using Openbabel\n",
    "res = Parallel(n_jobs=32, verbose=50,prefer='threads')(\n",
    "delayed(mob.obabel_optimize)(\n",
    "    mol= mol, \n",
    "    ff=\"gaff\",\n",
    "    coord_displace=True\n",
    "    ) for mol in fully_expanded_mols)\n",
    "\n",
    "res[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example 2: XTB Optimization via Job Mapping\n",
    "\n",
    "One can also take advantage of the jobmap functionality to run this optimization\n",
    "\n",
    "```python\n",
    "from molli.pipeline.xtb import XTBDriver\n",
    "\n",
    "#Serializes the molecule library as is\n",
    "source = ml.MoleculeLibrary('box_unoptimized.mlib', readonly=False)\n",
    "with source.writing():\n",
    "    for mol in fully_expanded_mols:\n",
    "        source[mol.name] = mol\n",
    "\n",
    "#This is the file the conformer ensembles calculated will be written to.\n",
    "destination = ml.MoleculeLibrary(\"box_optimized.mlib\", readonly=False)\n",
    "\n",
    "#This configures the driver, number of processes to use for each worker. Can also indicate how much memory to use.\n",
    "xtb = XTBDriver(nprocs=4)\n",
    "\n",
    "ml.pipeline.jobmap(\n",
    "    xtb.optimize_m,\n",
    "    source=source, #Source of molecules\n",
    "    destination=destination, #Where conformers will be written\n",
    "    cache_dir=\"./conf_cache\", #Where final outputs will be written, successful or not!\n",
    "    scratch_dir=\"/scratch/user/\", #Scratch Directory where calculations will be run\n",
    "    n_workers=4, #Number of workers to use. In this case, 4 workers, each with 16 processors as defined in the driver.\n",
    "    kwargs={\n",
    "        \"method\": \"gfnff\", #GFNFF method to be used\n",
    "    }, #These are arguments used in the xtb job\n",
    "    progress=True, #Will print out progress\n",
    "    verbose = True, #Will print out extra information\n",
    ")\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "dev-blake",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
